Release 10.1A: OpenEdge Development:
Programming Interfaces


Passing arrays as parameters

This section describes how you can pass arrays as parameters to and from DLL functions.

Note: You cannot pass an array of indeterminate extent to a DLL.

INTEGER and DECIMAL arrays

When a DLL Function requires an array of type BYTE, SHORT, UNSIGNED-SHORT, INT, LONG, FLOAT, or DOUBLE, you can pass an array of the appropriate Progress type (INTEGER or DECIMAL) as a parameter. You can use any parameter mode (INPUT, INPUT-OUTPUT, or OUTPUT). For the data type in the prototype, you can use just the type (for example, LONG) or you can specify it with the HANDLE TO option (for example, HANDLE TO). Progress always passes the array of values as a pointer so the HANDLE TO option is redundant, as it is with any INPUT-OUTPUT or OUTPUT parameter.

Here is an example C Code Prototype for a function called updateCounts:

updateCounts(short * parray); 

Here is the equivalent Progress 4GL Prototype for the updateCounts procedure.

PROCEDURE updateCounts EXTERNAL "myApp.dll" PERSISTENT: 
     DEFINE INPUT-OUTPUT PARAMETER parray AS SHORT. 
END. 

Here is the 4GL statement that executes the updateCounts procedure:

DEFINE VARIABLE cnts AS INTEGER EXTENT 5. 
     	. 
     	. 
     	. 
RUN updateCounts (cnts). 

CHARACTER and LONGCHAR arrays

If the DLL requires an array of strings as INPUT which is represented by an array of pointers to strings, you can pass a Progress CHARACTER or LONGCHAR array. You can do the same if it is an INPUT-OUTPUT parameter, however, this is not recommended. If the DLL updates the data such that the output string is longer than the input string, this can result in a memory exception or other unpredictable behavior. Therefore, for INPUT-OUTPUT parameters you should use a MEMPTR array, described in the "MEMPTR arrays" section.

Also, just as you cannot pass CHARACTER or LONGCHAR OUTPUT parameters to a DLL, you also cannot pass a CHARACTER or LONGCHAR array as an OUTPUT parameter. If the DLL requires an array of character buffers that it will modify or if the DLL allocates memory for a set of strings and returns them as an array of pointers, you should use a MEMPTR parameter.

As with the INTEGER and DECIMALtypes of arrays, the data type in the prototype can be either just the type (for example, CHARACTER) or you can specify it with the HANDLE TO option.

Here is an example C Code Prototype for a function called nameLookup:

nameLookup(char **ppStrArray, char *pfindName); 

Here is the equivalent Progress 4GL Prototype for the nameLookup procedure:

PROCEDURE nameLookup EXTERNAL "myApp.dll" PERSISTENT: 
     DEFINE INPUT PARAMETER ppStrArray AS HANDLE TO CHARACTER. 
     DEFINE INPUT PARAMETER pfindName  AS CHARACTER. 
END. 

Here is the 4GL statement that executes the nameLookup procedure:

DEFINE VAR names AS CHARACTER EXTENT 50. 
DEFINE VAR findName AS CHARACTER. 
     . 
     . 
     . 
RUN nameLookup(names, findName). 

MEMPTR arrays

If the DLL requires an array of pointers, where each pointer either points at a string or a structure, you can pass a Progress MEMPTR array. For INPUT or INPUT-OUTPUT parameters, you initialize each MEMPTR as appropriate to contain the string or structure to pass for INPUT. If it is an INPUT-OUTPUT parameter, you must insure that the allocated size (that is, the size set by SET-SIZE) is large enough to hold any expected output value, not just large enough to hold the input value. For an OUTPUT parameter, if the DLL expects an array of pointers to allocated buffers, you must use SET-SIZE to the required size for each MEMPTR in the array. If the DLL allocates memory for a set of strings or structures and returns them as an array of pointers, you must set each MEMPTR to at least the size of a pointer (for example, 4 or 8 bytes depending on the platform). You then use the GET-POINTER-VALUE and SET-POINTER-VALUE functions to access the data on return. (For more information on the GET- and SET-POINTER-VALUE functions, see OpenEdge Development: Progress 4GL Reference .) If you want to pass NULL as one or more of the pointers, the corresponding MEMPTR in the array can be a null MEMPTR, meaning that it is either uninitialized or you did a SET-SIZE on it to set it to zero length. For information on passing a MEMPTR parameter, see the "Using MEMPTR variables as parameters" section.

Here is an example C Code Prototype for a function called getNames:

getNames(char **pnameList); 

Here is the equivalent Progress 4GL Prototype for the getNames procedure. In this case, the DLL does not allocate the buffer, but expects to be passed an array of buffer pointers:

PROCEDURE getNames EXTERNAL "myApp.dll" PERSISTENT: 
     DEFINE OUTPUT PARAMETER names AS MEMPTR. 
END. 

Here is the 4GL statement that executes the getNames procedure:

DEFINE VAR names AS MEMPTR EXTENT 10. 
DEFINE VAR ix AS INTEGER. 
DO ix = 1 TO 10: 
     SET-SIZE(names[ix]) = 50. 
END. 
RUN getNames(names). 
DO ix = 1 TO 10: 
     DISPLAY GET-STRING(names[ix]). 
END.	 


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095